// Color definations
//

#ifndef __COLOR_H__
#define __COLOR_H__

// Define this to use RGB 24-bits drawing mode else assume in RGB 16-bits
// Note: if change this value, make sure to a clean build first!
#if !defined __RGB24 && !defined __RGB16 
#define	__RGB16		// default is __RGB16
#endif


// Define the byte order is 'Big Endian' (most significant byte first) or 
// 'Little Endian' (least significant byte first)
#if !defined _LITTLE_ENDIAN || !defined _BIG_ENDIAN
#define _BIG_ENDIAN	// default is _BIG_ENDIAN or same as color variable ordered
#endif


#ifdef __cplusplus
extern "C" {
#endif

#include "Common/Types.h"

// Un-define the WIN32's macros (declared in Wingdi.h, include Windows.h)
// Plz use _RGB, _GetRValue, _GetGValue, _GetBValue instead!
#undef   RGB
#undef   GetRValue 
#undef   GetGValue 
#undef   GetBValue 
/*
MEMO: rapped from win32
#define RGB(r,g,b)		((DWORD)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16)))
#define GetRValue(rgb)	((BYTE)(rgb))
#define GetGValue(rgb)	((BYTE)(((WORD)(rgb)) >> 8))
#define GetBValue(rgb)	((BYTE)((rgb)>>16))
*/

#if defined	__RGB24

	#define	_24BITS_COLOR		// use RGB 8-8-8 color space as default

#elif defined __RGB16

	#if !defined _15BITS_COLOR && !defined _16BITS_COLOR
	#ifdef _WIN32
		#define _15BITS_COLOR	// use RGB 5-5-5 color space in win32
	#else
		#define _16BITS_COLOR	// use RGB 5-6-5 color space as default
	#endif
	#endif

#else

	#error	__RGB16 or __RGB24 not defined!

#endif


#if defined __RGB16		// a pixel is 2-byte data

	// Defines converting methods
	#define  PIXEL_SIZE				2		
	#define  PIXEL_TO_BYTE(x)		((x) << 1)
	#define  BYTE_TO_PIXEL(x)		((x) >> 1)

	#define  WRITE_PIXEL_PTR(p,c)	(*((UInt16*)(p)) = (c))
	#define  READ_PIXEL_PTR(p)		(*((UInt16*)(p)))

#elif defined __RGB24	// a pixel is 3-byte triplet

	#define  PIXEL_SIZE				3		
	#define  PIXEL_TO_BYTE(x)		((x) * 3)
	#define  BYTE_TO_PIXEL(x)		((x) / 3)

	#if defined _LITTLE_ENDIAN
		// Byte order is little endian ordered
		#define  WRITE_PIXEL_PTR(p,c)	((*(p) = (UInt8)(c)),			\
						(*((p) + 1) = (UInt8)((c) >> 8)),	\
						(*((p) + 2) = (UInt8)((c) >> 16)))


		#define  READ_PIXEL_PTR(p)	(((UInt32) *(p)) |			\
						((UInt32) *((p) + 1) << 8) |		\
						((UInt32) *((p) + 2) << 16))

	#elif defined _BIG_ENDIAN

		// Byte order is big endian ordered or same as color variable ordered
		#define  WRITE_PIXEL_PTR(p,c)	((*(p)       = (UInt8)((c) >> 16)),	\
						(*((p) + 1) = (UInt8)((c) >> 8)),	\
						(*((p) + 2) = (UInt8)(c)))

		#define  READ_PIXEL_PTR(p)	(((UInt32) *(p) << 16) |		\
						((UInt32) *((p) + 1) << 8) |		\
						((UInt32) *((p) + 2)))
    #else

	#error	_LITTLE_ENDIAN or _BIG_ENDIAN not defined!

    #endif
#endif


// Pack the R,G,B values into a 16/24-bits color words
// NOTE: 1. the r,g,b values must between 0 and 255!
//		 2. should not use these directly, plz use _RGB macro
#define	 RGB555(r,g,b)		(((b) >> 3) | (((g) >> 3) << 5) | (((r) >> 3) << 10))
#define  RGB565(r,g,b)		(((b) >> 3) | (((g) >> 2) << 5) | (((r) >> 3) << 11))

#define  RGB888(r,g,b)		((b) | ((g) << 8) | ((r) << 16))
#define  BGR888(r,g,b)		((r) | ((g) << 8) | ((b) << 16))
#define  GBR888(r,g,b)		((r) | ((b) << 8) | ((g) << 16))
//#define  RGB888(r,g,b)	((UInt32)(((UInt8)(b)|((UInt16)((UInt8)(g))<<8))|(((UInt32)(UInt8)(r))<<16)))
//#define  BGR888(r,g,b)	((UInt32)(((UInt8)(r)|((UInt16)((UInt8)(g))<<8))|(((UInt32)(UInt8)(b))<<16)))
//#define  GBR888(r,g,b)	((UInt32)(((UInt8)(r)|((UInt16)((UInt8)(b))<<8))|(((UInt32)(UInt8)(g))<<16)))


#if defined _24BITS_COLOR

	#if defined __WIN32 || defined _BF533
		// Compute the color value from R,G,B components (0~255)
		#define	 _RGB			BGR888

		// Get R,G,B value from color
		#define  _GetRValue(c)	((UInt8)(c))
		#define  _GetGValue(c)	((UInt8)(((UInt16)(c)) >> 8))
		#define  _GetBValue(c)	((UInt8)((c) >> 16))

	#else // default

		#define	 _RGB			RGB888

		#define  _GetRValue(c)	((UInt8)((c) >> 16))
		#define  _GetGValue(c)	((UInt8)(((UInt16)(c)) >> 8))
		#define  _GetBValue(c)	((UInt8)(c))		

	#endif

#elif defined _15BITS_COLOR

	// Color bit mask for RGB555
	#define  R_BITMASK          0x7C00		// x1111100 00000000
	#define  G_BITMASK          0x03E0		// x0000011 11100000
	#define  B_BITMASK          0x001F		// x0000000 00011111

	#define  R_BITMASK64		0x7C007C007C007C00
	#define  G_BITMASK64		0x03E003E003E003E0
	#define  B_BITMASK64		0x001F001F001F001F

	#define  R_BITSHIFT			10

	#define  CLIP_BITMASK		0x3DEF3DEF	// x0111101 11101111 x0111101 11101111 

	// Compute the color value from R,G,B components (0~255)
	#define	 _RGB				RGB555

	// Get R,G,B value from color
	#define  _GetRValue(c)		(((c) >> 10) << 3)
	#define  _GetGValue(c)		(((c) & 0x03E0) >> 2)
	#define  _GetBValue(c)		(((c) & 0x001F) << 3)

#elif defined _16BITS_COLOR

	#define  R_BITMASK          0xF800		// 11111000 00000000
	#define  G_BITMASK          0x07E0		// 00000111 11100000
	#define  B_BITMASK          0x001F		// 00000000 00011111
                     
	#define  R_BITMASK64	    0xF800F800F800F800 
	#define  G_BITMASK64	    0x07E007E007E007E0 
	#define  B_BITMASK64	    0x001F001F001F001F
                     
	#define  R_BITSHIFT		    11	
                     
	#define  CLIP_BITMASK       0x7BEF7BEF	// 01111011 11101111 01111011 11101111

	#define	 _RGB				RGB565

	#define  _GetRValue(c)		(((c) >> 11) << 3)
	#define  _GetGValue(c)		(((c) & 0x07E0) >> 3)
	#define  _GetBValue(c)		(((c) & 0x001F) << 3)

#else

	#error  Color space not defined!

#endif
   
#ifdef __cplusplus
}
#endif

#endif  // __COLOR_H__
